home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 7 / Apprentice-Release7.iso / Source Code / Pascal / Snippets / PNL Libraries / MyListWindow.p < prev    next >
Text File  |  1997-03-18  |  21KB  |  819 lines

  1. unit MyListWindow;
  2.  
  3. interface
  4.  
  5.     uses
  6.         Types, Events, Lists, Drag, Controls, Quickdraw, 
  7.         MyOOMainLoop;
  8.  
  9.     type
  10.         ListWindowObject = object(DObject)
  11.                 list: ListHandle;
  12.                 hcontrol: ControlHandle;
  13.                 list_offset, list_width, max_display_width, header_height: integer;
  14.                 typed_chars: Str31;
  15.                 typed_time: longint;
  16.                 never_drag: boolean;
  17.                 list_item: integer;
  18.                 procedure CreateList (font, size: integer; listitem: integer; ldefID: integer; hscroll: boolean);
  19.                 procedure Destroy;
  20.                 override;
  21.                 procedure DoItemWhere (const er: EventRecord; item: integer);
  22.                 override;
  23.                 procedure Resize;
  24.                 override;
  25.                 procedure DrawGrow;
  26.                 override;
  27.                 procedure DoActivateDeactivate (activate: boolean);
  28.                 override;
  29.                 procedure DoKey (const er:EventRecord; ch: char);
  30.                 override;
  31.                 function Match (c: Cell; var what: Str255): boolean;
  32.                 procedure Find (what: Str255; fromstart, allatonce, backwards: boolean);
  33.                 procedure AdjustHContol (canRedraw: BOOLEAN);
  34.                 procedure SetListWidth (max: integer);
  35.                 procedure UpdateZoomHeight;
  36.                 function DontDrag (er: EventRecord): boolean;
  37.                 function DoLClick (er: EventRecord): boolean;
  38.                 procedure DoDoubleClick;
  39.                 procedure DoDoubleClickCell (c: Cell);
  40.                 function GetEntryName (c: Cell): Str255;
  41.                 function GetUniqueEntryName (c: Cell): Str255;
  42.                 procedure OpenParent;
  43.                 procedure LDEF (message: integer; select: boolean; var r: Rect; c: Cell; dataOffset, dataLen: integer);
  44.                 procedure DrawHeader (r: Rect);
  45.                 procedure DoHeaderClick (r: Rect; where: Point; const er: EventRecord );
  46.                 procedure SetSingleSelection (v: integer);
  47.                 function SelectFirstAfter (s: Str255): boolean;
  48.                 function SelectFirstBefore (s: Str255): boolean;
  49.                 function GetFirstSelection (var c: Cell): boolean;
  50.                 function GetLastSelection (var c: Cell): boolean;
  51.                 function CountSelections: integer;
  52.                 function IsSelection: boolean;
  53.                 function DoSetupDragCell (c: Cell; dragref: DragReference; dragrgn: RgnHandle): OSErr;
  54.                 function DoSetupDrag (dragref: DragReference; dragrgn: RgnHandle): OSErr;
  55.                 override;
  56.                 procedure RedrawLine( line: integer );
  57.                 procedure DrawUserItem( item: integer );
  58.                 override;
  59.             end;
  60.  
  61.     procedure StartupMyListWindow;
  62.     
  63. implementation
  64.  
  65.     uses
  66.         ToolUtils, Drag, Dialogs, OSUtils, QuickdrawText, TextUtils, Windows, 
  67.         MyDialogs, MyAssertions, MyStartup, MyTypes, MyMathUtils, 
  68.         MySystemGlobals, MyListManager, MyCursors, MyCallProc,
  69.         SmartScrollAPI;
  70.  
  71. {$ifc do_debug}
  72.     var
  73.         startup_check: integer;
  74. {$endc}
  75.  
  76.     var
  77.         gCallLDEFProc : UniversalProcPtr;
  78.         gHActionProc : UniversalProcPtr;
  79.         
  80.     procedure ListWindowObject.DrawUserItem( item: integer );
  81.         var
  82.             list_rect, header_rect: Rect;
  83.     begin
  84.         SetPort( window );
  85.         if item = list_item then begin
  86.             PenNormal;
  87.             GetDItemRect( window, item, list_rect );
  88.             header_rect := list_rect;
  89.             list_rect.top := list_rect.top + Choose( header_height > 0, header_height + 1, 0);
  90.             InsetRect( list_rect, -1, -1 );
  91.             FrameRect( list_rect );
  92.             if header_height > 0 then begin
  93.                 header_rect.bottom := header_rect.top + header_height;
  94.                 DrawHeader( header_rect );
  95.             end;
  96.             DrawGrow;
  97.             LUpdate( window^.visRgn, list );
  98.         end else begin
  99.             inherited DrawUserItem( item );
  100.         end;
  101.     end;
  102.  
  103.     function ListWindowObject.Match (c: Cell; var what: Str255): boolean;
  104.     begin
  105. {$unused(c, what)}
  106.         Match := false;
  107.     end;
  108.  
  109.     procedure ListWindowObject.Find (what: Str255; fromstart, allatonce, backwards: boolean);
  110.         var
  111.             c: Cell;
  112.             found, found1: boolean;
  113.     begin
  114.         if allatonce then begin
  115.             found := false;
  116.             c.v := 0;
  117.             c.h := 0;
  118.             while (c.v < LCount( list )) do begin
  119.                 found1 := Match(c, what);
  120.                 LSetSelect(found1, c, list);
  121.                 if found1 then begin
  122.                     found := true;
  123.                 end;
  124.                 c.v := c.v + 1;
  125.             end;
  126.         end else begin
  127.             if backwards then begin
  128.                 if fromstart then begin
  129.                     c.v := LCount( list )-1;
  130.                     c.h := 0;
  131.                 end else begin
  132.                     c.v := 0;
  133.                     c.h := 0;
  134.                     if LGetSelect(true, c, list) then begin
  135.                         c.v:=c.v-1;
  136.                     end else begin
  137.                         c.v := LCount( list )-1;
  138.                         c.h := 0;
  139.                     end;
  140.                 end;
  141.                 found := false;
  142.                 while (c.v >=0) do begin
  143.                     found := Match(c, what);
  144.                     if found then begin
  145.                         leave;
  146.                     end;
  147.                     c.v := c.v - 1;
  148.                 end;
  149.             end else begin
  150.                 c.v := 0;
  151.                 c.h := 0;
  152.                 if not fromstart then begin
  153.                     while LGetSelect(true, c, list) do begin
  154.                         c.v := c.v + 1;
  155.                         c.h := 0;
  156.                     end;
  157.                 end;
  158.                 found := false;
  159.                 while (c.v < LCount( list )) do begin
  160.                     found := Match(c, what);
  161.                     if found then begin
  162.                         leave;
  163.                     end;
  164.                     c.v := c.v + 1;
  165.                 end;
  166.             end;
  167.             if found then begin
  168.                 SetSingleSelection(c.v);
  169.             end;
  170.         end;
  171.         if not found then begin
  172.             SysBeep(1);
  173.         end;
  174.     end;
  175.  
  176.     procedure ListWindowObject.LDEF (message: integer; select: boolean; var r: Rect; c: Cell; dataOffset, dataLen: integer);
  177.     begin
  178. {$unused(message, select, r, c, dataOffset, dataLen)}
  179.     end;
  180.  
  181.     procedure ListWindowObject.DrawHeader (r: Rect);
  182.     begin
  183. {$unused(r)}
  184.     end;
  185.  
  186.     procedure ListWindowObject.DoHeaderClick (r: Rect; where: Point; const er: EventRecord );
  187.     begin
  188. {$unused(r, where, er)}
  189.     end;
  190.  
  191.     procedure CallLDEF (message: integer; select: boolean; var r: Rect; c: Cell; dataOffset, dataLen: integer; lh: ListHandle);
  192.         var
  193.             obj:WObject; { BUG IN MWP }
  194.     begin
  195.         obj:=GetWObject(lh^^.port);
  196.         ListWindowObject(obj).LDEF(message, select, r, c, dataOffset, dataLen);
  197.     end;
  198.  
  199.     procedure ListWindowObject.SetListWidth (max: integer);
  200.     begin
  201.         list_width := max;
  202.         zoomSize.h := max + 16;
  203.         UpdateZoomHeight;
  204.         AdjustHContol(true);
  205.     end;
  206.     
  207.     procedure ListWindowObject.UpdateZoomHeight;
  208.         var
  209.             zv: longint;
  210.     begin
  211.         zv := longint(list^^.cellSize.v) * longint(LCount( list )) + 16 + header_height;
  212.         if zv > 30000 then begin
  213.             zoomSize.v := 30000;
  214.         end else begin
  215.             zoomSize.v := zv;
  216.         end;
  217.     end;
  218.  
  219.     procedure ListWindowObject.AdjustHContol (canRedraw: BOOLEAN);
  220. {Calculate the new control maximum value and current value }
  221. {max is calculated by comparing the maximum document}
  222. {width to the width of the viewRect. The current values are set by comparing the offset between}
  223. {the view and destination rects. If necessary and we canRedraw, have the control be re-drawn by}
  224. {calling ShowControl.}
  225.         var
  226.             max: integer;
  227.             oldValue, oldMax: integer;
  228.             cliprgn: RgnHandle;
  229.             r: Rect;
  230.             viswidth: integer;
  231.     begin
  232.         oldValue := GetControlValue(hcontrol);
  233.         oldMax := GetControlMaximum(hcontrol);
  234.         GetDItemRect(window, list_item, r);
  235.         max := list_width - (r.right - 16 - r.left);
  236.         if max < 0 then begin
  237.             max := 0;            {check for negative values}
  238.         end;
  239.         list_offset := Pin(0, oldValue, max);
  240.         SetPort(window);
  241.         cliprgn := NewRgn;
  242.         GetClip(cliprgn);
  243.         SetRect(r, 0, 0, 0, 0);
  244.         ClipRect(r);
  245.         SetControlMaximum(hcontrol, max);
  246.         SetClip(cliprgn);
  247.         DisposeRgn(cliprgn);
  248.         SetControlValue(hcontrol, list_offset);
  249.         viswidth := list^^.rView.right - list^^.rView.left;
  250.         SetSmartScrollInfo( hcontrol, viswidth, max + viswidth );
  251.         if canRedraw and ((max <> oldMax) or (list_offset <> oldValue)) then begin
  252.             ShowControl(hcontrol);            {check to see if the control can be re-drawn}
  253.         end;
  254.     end;
  255.  
  256.     procedure ListWindowObject.CreateList (font, size: integer; listitem: integer; ldefID: integer; hscroll: boolean);
  257.         var
  258.             view, bounds: Rect;
  259.             siz: Point;
  260.             fi: FontInfo;
  261.             dr: Rect;
  262.     begin
  263.         AssertDidStartup( startup_check );
  264.         list_item := listitem;
  265.         handle_shift_tab := false;
  266.         never_drag := true;
  267.         typed_time := 0;
  268.         max_display_width := maxInt;
  269.         header_height := 0;
  270.         SetPort(window);
  271.         TextFont(font);
  272.         TextSize(size);
  273.         GetFontInfo(fi);
  274.         draw_grow_icon := true;
  275.         GetDItemRect( window, list_item, view );
  276.         HandleAllUserItems;
  277.         SetRect(bounds, 0, 0, 1, 0);
  278.         view.right := view.right - 15;
  279.         SetPt(siz, 30000, fi.ascent + fi.descent + fi.leading);
  280.         list := LNew(view, bounds, siz, ldefID, window, true, true, false, true);
  281.         list^^.refCon := longint(gCallLDEFProc);
  282.         if hscroll then begin
  283.             SetRect(dr, 0, 0, 100, 16);
  284.             hcontrol := NewControl(window, dr, '', true, 0, 0, 0, scrollBarProc, 0);
  285.         end else begin
  286.             hcontrol := nil;
  287.         end;
  288.         Resize;
  289.     end;
  290.  
  291.     procedure ListWindowObject.Destroy;
  292.     begin
  293.         LDispose(list);
  294.         inherited Destroy;
  295.     end;
  296.  
  297.     procedure ListWindowObject.DoDoubleClickCell (c: Cell);
  298.     begin
  299. {$unused(c)}
  300.     end;
  301.  
  302.     function ListWindowObject.DoSetupDragCell (c: Cell; dragref: DragReference; dragrgn: RgnHandle): OSErr;
  303.     begin
  304. {$unused(c, dragref, dragrgn)}
  305.         DoSetupDragCell := -1;
  306.     end;
  307.  
  308.     function ListWindowObject.DoSetupDrag (dragref: DragReference; dragrgn: RgnHandle): OSErr;
  309.         var
  310.             c: Cell;
  311.             err: OSErr;
  312.     begin
  313.         err := -23;
  314.         c.h := 0;
  315.         c.v := 0;
  316.         while LGetSelect(true, c, list) do begin
  317.             err := DoSetupDragCell(c, dragref, dragrgn);
  318.             if err <> noErr then begin
  319.                 leave;
  320.             end;
  321.             c.v := c.v + 1;
  322.             c.h := 0;
  323.         end;
  324.         DoSetupDrag := err;
  325.     end;
  326.  
  327.     type
  328.         ClickLoopData = record
  329.             first_call: boolean;
  330.             first_point: Point;
  331.             er: EventRecord;
  332.             wobj: WObject;
  333.         end; 
  334.         ClickLoopDataPtr = ^ClickLoopData;
  335.  
  336.     function MyClickLoop( list: ListHandle; data: ClickLoopDataPtr ) : boolean;
  337.         var
  338.             r, cellRect: Rect;
  339.             cellClicked: Cell;
  340.             curPt: Point;
  341.             dummy: boolean;
  342.             ret: boolean;
  343.     begin
  344.         ret := true;
  345.         if data^.first_call then begin
  346.             data^.first_call := false;
  347.             GetMouse(data^.first_point);
  348.         end else begin
  349.             SetRect(r, data^.first_point.h - 3, data^.first_point.v - 3, data^.first_point.h + 3, data^.first_point.v + 3);
  350.             cellClicked := LLastClick(list);
  351.             LRect(cellRect, cellClicked, list);
  352.             dummy := SectRect(r, cellRect, r);
  353.             GetMouse(curPt);
  354.             if not PtInRect(curPt, r) then begin
  355.                 data^.wobj.DoTrackDrag(data^.er);
  356.                 ret := false;
  357.             end;
  358.         end;
  359.         MyClickLoop := ret;
  360.     end;
  361.  
  362.     function ListWindowObject.DontDrag (er: EventRecord): boolean;
  363.     begin
  364. {$unused(er)}
  365.         DontDrag := never_drag or last_event_had_shift or last_event_had_command;
  366.     end;
  367.  
  368.     function ListWindowObject.DoLClick (er: EventRecord): boolean;
  369.         var
  370.             double: boolean;
  371.             local: Point;
  372.             data: ClickLoopData;
  373.     begin
  374.         local := er.where;
  375.         GlobalToLocal(local);
  376.         if not has_DragManager or DontDrag(er) then begin
  377.             CursorSetProcessing(false);
  378.             double := LClick(local, er.modifiers, list);
  379.         end else begin
  380.             data.first_call := true;
  381.             data.er := er;
  382.             data.wobj := self;
  383.             CursorSetProcessing(false);
  384.             double := LClickSafe(local, er.modifiers, list, MyClickLoop, @data);
  385.         end;
  386.         DoLClick := double;
  387.     end;
  388.  
  389.     procedure ListWindowObject.OpenParent;
  390.     begin
  391.     end;
  392.  
  393.     procedure ListWindowObject.SetSingleSelection (v: integer);
  394.     begin
  395.         LUpdate(WindowPeek(window)^.updateRgn, list);
  396.         LSetSingleSelection(list, v);
  397.         LAutoScroll(list);
  398.     end;
  399.  
  400.     procedure ListWindowObject.DoDoubleClick;
  401.         var
  402.             c: Cell;
  403.     begin
  404.         c.h := 0;
  405.         c.v := 0;
  406.         while LGetSelect(true, c, list) do begin
  407.             DoDoubleClickCell(c);
  408.             c.v := c.v + 1;
  409.             c.h := 0;
  410.         end;
  411.     end;
  412.  
  413.     var
  414.         action_listobj: ListWindowObject;
  415.  
  416.     procedure CommonAction (control: ControlHandle; var amount: integer);
  417.         var
  418.             value, max, ovalue: integer;
  419.     begin
  420.         value := GetControlValue(control);
  421.         ovalue := value;
  422.         max := GetControlMaximum(control);
  423.         value := Pin(0, value - amount, max);
  424.         if value <> ovalue then begin
  425.             SetControlValue(control, value);
  426.         end;
  427.         amount := ovalue - value;   { calculate true change }
  428.     end; { CommonAction  }
  429.  
  430. { Determines how much to change the value of the horizontal scrollbar by and how }
  431. { much to scroll the TE record. }
  432.     procedure HAction (control: ControlHandle; part: integer);
  433.         var
  434.             amount: integer;
  435.             window: WindowPtr;
  436.     begin
  437.         if (part <> 0) then begin
  438.             window := action_listobj.window;
  439.             case part of
  440.                 kControlUpButtonPart, kControlDownButtonPart:    begin    { a few pixels }
  441.                     amount := 8;
  442.                 end;
  443.                 kControlPageUpPart, kControlPageDownPart: begin        { a page width }
  444.                     with action_listobj.list^^.rView do begin
  445.                         amount := (right - left);
  446.                     end;
  447.                 end;
  448.             end;
  449.             if ((part = kControlDownButtonPart) or (part = kControlPageDownPart)) then begin
  450.                 amount := -amount;        { reverse direction }
  451.             end;
  452.             CommonAction(control, amount);
  453.             if amount <> 0 then begin
  454.                 action_listobj.list_offset := GetControlValue(control);
  455.                 action_listobj.DrawUserItem( action_listobj.list_item);
  456.             end;
  457.         end;
  458.     end;
  459.  
  460.     function ListWindowObject.GetEntryName (c: Cell): Str255;
  461.     begin
  462. {$unused(c)}
  463.         GetEntryName := '';
  464.     end;
  465.  
  466.     function ListWindowObject.GetUniqueEntryName (c: Cell): Str255;
  467.     begin
  468.         GetUniqueEntryName := concat(GetEntryName(c), chr(0), chr(c.v div 256), chr(c.v mod 256));
  469.     end;
  470.  
  471.     function ListWindowObject.SelectFirstAfter (s: Str255): boolean;
  472.         var
  473.             i, index: integer;
  474.             c: Cell;
  475.             best, n: Str255;
  476.             good: boolean;
  477.     begin
  478.         good := false;
  479.         best := concat(chr(255), chr(255));
  480.         for i := 0 to LCount( list ) - 1 do begin
  481.             c.h := 0;
  482.             c.v := i;
  483.             n := GetUniqueEntryName(c);
  484.             if (IUCompString(s, n) < 0) & (IUCompString(n, best) < 0) then begin
  485.                 best := n;
  486.                 index := c.v;
  487.                 good := true;
  488.             end;
  489.         end;
  490.         if good then begin
  491.             SetSingleSelection(index);
  492.         end;
  493.         SelectFirstAfter := good;
  494.     end;
  495.  
  496.     function ListWindowObject.SelectFirstBefore (s: Str255): boolean;
  497.         var
  498.             i, index: integer;
  499.             c: Cell;
  500.             best, n: Str255;
  501.             good: boolean;
  502.     begin
  503.         good := false;
  504.         index := 0;
  505.         best := '';
  506.         for i := 0 to LCount( list ) - 1 do begin
  507.             c.h := 0;
  508.             c.v := i;
  509.             n := GetUniqueEntryName(c);
  510.             if (IUCompString(s, n) > 0) & (IUCompString(n, best) > 0) then begin
  511.                 best := n;
  512.                 index := c.v;
  513.                 good := true;
  514.             end;
  515.         end;
  516.         if good then begin
  517.             SetSingleSelection(index);
  518.         end;
  519.         SelectFirstBefore := good;
  520.     end;
  521.  
  522.     function ListWindowObject.GetFirstSelection (var c: Cell): boolean;
  523.         var
  524.             best, n: Str255;
  525.             index: integer;
  526.     begin
  527.         GetFirstSelection := false;
  528.         c.h := 0;
  529.         c.v := 0;
  530.         best := concat(chr(255), chr(255));
  531.         while LGetSelect(true, c, list) do begin
  532.             GetFirstSelection := true;
  533.             n := GetUniqueEntryName(c);
  534.             if IUCompString(n, best) < 0 then begin
  535.                 index := c.v;
  536.             end;
  537.             c.v := c.v + 1;
  538.         end;
  539.         c.h := 0;
  540.         c.v := index;
  541.     end;
  542.  
  543.     function ListWindowObject.GetLastSelection (var c: Cell): boolean;
  544.         var
  545.             best, n: Str255;
  546.             index: integer;
  547.     begin
  548.         GetLastSelection := false;
  549.         c.h := 0;
  550.         c.v := 0;
  551.         best := '';
  552.         while LGetSelect(true, c, list) do begin
  553.             GetLastSelection := true;
  554.             n := GetUniqueEntryName(c);
  555.             if IUCompString(n, best) > 0 then begin
  556.                 index := c.v;
  557.             end;
  558.             c.v := c.v + 1;
  559.         end;
  560.         c.h := 0;
  561.         c.v := index;
  562.     end;
  563.  
  564.     procedure ListWindowObject.DoKey (const er:EventRecord; ch: char);
  565.         var
  566.             c: Cell;
  567.             index: integer;
  568.             dummy: boolean;
  569.             onlyoneselection: boolean;
  570.     begin
  571. {$unused(er)}
  572.         onlyoneselection := BAND(list^^.selFlags, lOnlyOne) <> 0;
  573.         if ch < ' ' then begin
  574.             typed_time := 0;
  575.         end;
  576.         case ord(ch) of
  577.             downArrowChar:  begin
  578.                 if last_event_had_command then begin
  579.                     DoDoubleClick;
  580.                 end else begin
  581.                     ObscureCursor;
  582.                     if LCount( list ) > 0 then begin
  583.                         if LGetLastSelection(list, c) then begin
  584.                             index := c.v + 1;
  585.                         end else begin
  586.                             index := 0;
  587.                         end;
  588.                         if index >= LCount( list ) then begin
  589.                             index := LCount( list ) - 1;
  590.                         end;
  591.                         if onlyoneselection or not last_event_had_shift then begin
  592.                             SetSingleSelection(index);
  593.                         end else begin
  594.                             c.v := index;
  595.                             LSetSelect(true, c, list);
  596.                         end;
  597.                     end;
  598.                 end;
  599.             end;
  600.             upArrowChar:  begin
  601.                 if last_event_had_command then begin
  602.                     OpenParent;
  603.                 end else begin
  604.                     ObscureCursor;
  605.                     if LCount( list ) > 0 then begin
  606.                         if not LGetFirstSelection(list, c) then begin
  607.                             c.v := LCount( list );
  608.                         end;
  609.                         c.v := c.v - 1;
  610.                         if c.v < 0 then begin
  611.                             c.v := 0;
  612.                         end;
  613.                         if onlyoneselection or not last_event_had_shift then begin
  614.                             SetSingleSelection(c.v);
  615.                         end else begin
  616.                             LSetSelect(true, c, list);
  617.                         end;
  618.                     end;
  619.                 end;
  620.             end;
  621.             homeChar:  begin
  622.                 ObscureCursor;
  623.                 LScroll(0, -LCount( list ), list);
  624.             end;
  625.             endChar:  begin
  626.                 ObscureCursor;
  627.                 LScroll(0, LCount( list ), list);
  628.             end;
  629.             pageUpChar:  begin
  630.                 ObscureCursor;
  631.                 LScroll(0, -(list^^.visible.bottom - list^^.visible.top - 2), list);
  632.             end;
  633.             pageDownChar:  begin
  634.                 ObscureCursor;
  635.                 LScroll(0, (list^^.visible.bottom - list^^.visible.top - 2), list);
  636.             end;
  637.             tabChar:  begin
  638.                 ObscureCursor;
  639.                 if last_event_had_shift then begin
  640.                     if not GetFirstSelection(c) | not SelectFirstBefore(GetUniqueEntryName(c)) then begin
  641.                         dummy := SelectFirstBefore(chr(255));
  642.                     end;
  643.                 end else begin
  644.                     if not GetLastSelection(c) | not SelectFirstAfter(GetUniqueEntryName(c)) then begin
  645.                         dummy := SelectFirstAfter('');
  646.                     end;
  647.                 end;
  648.             end;
  649.             3, 13:  begin
  650.                 DoDoubleClick;
  651.             end;
  652.             otherwise begin
  653.                 ObscureCursor;
  654.                 if ch >= ' ' then begin
  655.                     if last_event_time - typed_time > 60 then begin
  656.                         typed_chars := '';
  657.                     end;
  658.                     typed_time := last_event_time;
  659.                     typed_chars := concat(typed_chars, ch);
  660.                     if not SelectFirstAfter(typed_chars) then begin
  661.                         dummy := SelectFirstBefore(chr(255));
  662.                     end;
  663.                 end;
  664.             end;
  665.         end;
  666. { WARNING: self may have been destroyed! }
  667.     end;
  668.  
  669.     procedure ListWindowObject.DoItemWhere (const er: EventRecord; item: integer);
  670.         var
  671.             didit: boolean;
  672.             ctl: ControlHandle;
  673.             part, value: integer;
  674.             r: Rect;
  675.             local: Point;
  676.     begin
  677.         if item = list_item then begin
  678.             SetPort(window);
  679.             local := er.where;
  680.             GlobalToLocal(local);
  681.             if local.v < header_height then begin
  682.                 GetDItemRect(window, list_item, r);
  683.                 r.bottom := r.top + header_height;
  684.                 DoHeaderClick(r, local, er);
  685.             end else begin
  686.                 didit := false;
  687.                 if hcontrol <> nil then begin
  688.                     part := FindControl(local, window, ctl);
  689.                     if ctl = hcontrol then begin
  690.                         didit := true;
  691.                         if part = kControlIndicatorPart then begin
  692.                             value := GetControlValue(hcontrol);
  693.                             part := TrackControl(hcontrol, local, nil);
  694.                             if part <> 0 then begin
  695.                                 list_offset := GetControlValue(hcontrol);
  696.                                 if value <> list_offset then begin
  697.                                     InvalRect(window^.portRect);
  698.                                 end;
  699.                             end;
  700.                         end else begin
  701.                             action_listobj := self;
  702.                             value := TrackControl(hcontrol, local, gHActionProc);
  703.                         end;
  704.  
  705.                     end;
  706.                 end;
  707.                 if not didit & DoLClick(er) then begin
  708.                     DoDoubleClick;
  709.                 end;
  710.             end;
  711.         end else begin
  712.             inherited DoItemWhere(er, item);
  713.         end;
  714.     end;
  715.  
  716.     procedure ListWindowObject.DoActivateDeactivate (activate: boolean);
  717.     begin
  718.         LActivate(activate, list);
  719.         if hcontrol <> nil then begin
  720.             if activate then begin
  721.                 ShowControl(hcontrol);
  722.             end else begin
  723.                 HideControl(hcontrol);
  724.             end;
  725.         end;
  726.         inherited DoActivateDeactivate(activate);
  727.     end;
  728.  
  729.     procedure ListWindowObject.Resize;
  730.         const
  731.             invis = 0;
  732.             vis = 255;
  733.         var
  734.             r: Rect;
  735.             width, height, nheight, lineheight: integer;
  736.     begin
  737.         SetPort(window);
  738.         lineheight := list^^.cellSize.v;
  739.         width := window^.portRect.right - window^.portRect.left;
  740.         height := window^.portRect.bottom - window^.portRect.top;
  741.         nheight := (height - header_height - 16) mod lineheight;
  742.         if nheight <> 0 then begin
  743.             SizeWindow(window, width, height - nheight, false);
  744.         end;
  745.         growRect.top := (50 + lineheight - 1) div lineheight * lineheight + header_height + 16;
  746.         r.left := 0;
  747.         r.right := window^.portRect.right + 1;
  748.         if r.right > max_display_width then begin
  749.             r.right := max_display_width;
  750.         end;
  751.         r.top := 0;
  752.         r.bottom := window^.portRect.bottom;
  753.         SetDItemRect(window, list_item, r);
  754.         r.top := r.top + Choose( header_height > 0, header_height + 1, 0);
  755.         r.bottom := r.bottom - 15;
  756.         height := r.bottom - r.top;
  757.         list^^.rView.topLeft := r.topLeft; { LMove???? }
  758.         LSize(r.right - r.left - 16, height, list);
  759.         if hcontrol <> nil then begin
  760.             hcontrol^^.contrlVis := invis;
  761.             MoveControl(hcontrol, r.left, r.bottom);
  762.             SizeControl(hcontrol, r.right - r.left - 15, 16);
  763.             AdjustHContol(false);
  764.             hcontrol^^.contrlVis := vis;
  765.         end;
  766.         UpdateZoomHeight;
  767.         InvalRect(window^.portRect);
  768.         inherited Resize;
  769.     end;
  770.  
  771.     procedure ListWindowObject.DrawGrow;
  772.         var
  773.             r: Rect;
  774.     begin
  775.         SetRect(r, -30000, header_height + 1, 30000, 30000);
  776.         DrawTheFriggingGrowIcon(window, r);
  777.     end;
  778.  
  779.     function ListWindowObject.CountSelections: integer;
  780.     begin
  781.         CountSelections := LCountSelections(list);
  782.     end;
  783.  
  784.     function ListWindowObject.IsSelection: boolean;
  785.     begin
  786.         IsSelection := LHasSelection(list);
  787.     end;
  788.  
  789.     procedure ListWindowObject.RedrawLine( line: integer );
  790.         var
  791.             c: Cell;
  792.     begin
  793.         c.v := line;
  794.         c.h := 0;
  795.         LDraw( c, list );
  796.     end;
  797.     
  798.     function InitMyListWindow(var msg: integer): OSStatus;
  799.     begin
  800. {$unused(msg)}
  801.         DidStartup( startup_check );
  802.         DidStartup( startup_check );
  803.         gCallLDEFProc := NewListDefProc(CallLDEF);
  804.         gHActionProc := NewControlActionProc(HAction);
  805.         InitMyListWindow := noErr;
  806.     end;
  807.     
  808.     procedure StartupMyListWindow;
  809.     begin
  810.         StartupDialogs;
  811.         SetStartup( InitMyListWindow, nil, 0, nil );
  812.     end;
  813.     
  814. end.
  815.     function MyClickLoop: boolean; { returns the bloody equal flag for gods sake! }
  816.     begin
  817.         MyClickLoop := MyClickLoop2; { BE VERY CAREFUL!  Returns the equal flag! }
  818.     end;
  819.